package com.example.service.impl;

import com.example.global.GlobalWord;
import com.example.pojo.Qualification;
import com.example.pojo.SysOffice;
import com.example.pojo.SysUser;
import com.example.req.QualificationTaskReq;
import com.example.service.IQualificationService;
import com.example.service.ISysOfficeService;
import com.example.service.ISysUserService;
import com.example.service.QualificationProcessService;
import com.example.utils.Utils;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.apache.commons.collections.ListUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class QualificationProcessServiceImpl implements QualificationProcessService {
    @Autowired
    RepositoryService repositoryService;
    @Autowired
    RuntimeService runtimeService;
    @Autowired
    TaskService taskService;
    @Autowired
    HistoryService historyService;
    @Autowired
    IQualificationService qualificationService;
    @Autowired
    ISysOfficeService sysOfficeService;
    @Autowired
    ISysUserService userService;

    /**
     * 开启资质审核流程
     * @param qualification
     * @return
     */
    @Override
    @Transactional
    public boolean startQualification(Qualification qualification) {
        //插入资质申请单
        boolean save = qualificationService.save(qualification);
        System.out.println("回填的id" + qualification.getId());

        //合成businessKey
        String key = GlobalWord.qualificationKey;
        String businessKey = key + "." + qualification.getId();
        //设置流程的关联操作人ID
        Map<String, Object> map = new HashMap<>();
        map.put("organizationUserId", qualification.getUploadUserId());
        //获取资质审核人员的ID集合
        List<SysUser> list = userService.queryByRoleId(29L);
        List<Long> idList = list.stream().map(e -> e.getId()).collect(Collectors.toList());
        String ids = Utils.listToString(idList);

        map.put(GlobalWord.qualificationAuditor, ids);
        //开启流程
        runtimeService.startProcessInstanceByKey(key, businessKey, map);

        return save;
    }

    /**
     * 根据用户ID获取任务集合
     * @param id
     * @return
     */
    @Override
    public List<Task> queryQualificationTaskByUserId(Long id) {
        //根据用户组查询(该操作需要SpringSecurity支持，不然报异常)
        List<Task> list = taskService.createTaskQuery()
                .processDefinitionKey(GlobalWord.qualificationKey)
                .taskCandidateUser(id.toString())
                .list();

        //根据Assignee查询
        List<Task> list1 = taskService.createTaskQuery()
                .processDefinitionKey(GlobalWord.qualificationKey)
                .taskAssignee(id.toString())
                .list();

        //将两个任务集合合并返回
        list.addAll(list1);
        return list;
    }

    /**
     * 根据TaskId获取businessKey
     * @param taskId
     * @return
     */
    @Override
    public String getBusinessKeyByTaskId(String taskId) {
        //1、获取任务对象
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        //2、根据流程实例ID获取流程实例，进一步获取businessKey返回
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(task.getProcessInstanceId())
                .singleResult();
        return processInstance.getBusinessKey();
    }

    /**
     * 根据TaskId获取关联批注
     * @param taskId
     * @return
     */
    @Override
    public List<Comment> queryAllCommentByTaskId(String taskId) {
        //1、获取任务对象
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        //2、获取批注集合返回
        List<Comment> comments = taskService.getProcessInstanceComments(task.getProcessInstanceId());
        return comments;
    }

    /**
     * 根据taskID获取当前节点的出口连线名称集合
     * @param taskId
     * @return
     */
    @Override
    public List<String> queryButtonListByTaskId(String taskId) {
        // 获取当前任务
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        //获取当前模型
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        // 获取当前节点
        FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey());
        UserTask userTask = (UserTask) flowElement;
        //获取节点出口线段
        List<SequenceFlow> outgoingFlows = userTask.getOutgoingFlows();
        List<String> collect = outgoingFlows.stream()
                .map(e -> e.getName() == null ? "默认提交" : e.getName())
                .collect(Collectors.toList());

        return collect;
    }

    /**
     * 资质审核流程推进
     * @param info
     * @return
     */
    @Override
    @Transactional
    public boolean complete(QualificationTaskReq info) {
        //更新资质申请单
        if (info.getQualification() != null) {
            qualificationService.updateById(info.getQualification());
        }

        //获取任对象和businessKey
        Task task = taskService.createTaskQuery()
                .taskId(info.getTaskId())
                .singleResult();
        String businessKey = getBusinessKeyByTaskId(task.getId());

        //若当前节点是对对人开放操作，则推进前先领取任务，避免多人同时操作发生冲突
        if (task.getAssignee() == null) {
            //领取任务，相当于设置assignee，领取任务后，他人不能再领取
            taskService.claim(info.getTaskId(), info.getUserId().toString());
            //更新资质申请单对应的资质审核人
            Qualification qualification = qualificationService.getById(businessKey.split("\\.")[1]);
            qualification.setCheckUserId(info.getUserId());
            qualificationService.updateById(qualification);
        }

        //设置批注人以及批注信息
        Authentication.setAuthenticatedUserId(info.getUserId().toString());
        taskService.addComment(task.getId(), task.getProcessInstanceId(), info.getComment());

        //添加流程推进的条件并推进
        Map<String, Object> map = new HashMap<>();
        map.put("msg", info.getButtonValue());
        taskService.complete(task.getId(), map);

        //获取流程实例
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceBusinessKey(businessKey)
                .singleResult();

        //判断流程是否结束，若结束则更新对应记录信息
        if (processInstance == null){
            //更新资质单状态
            Qualification qualification = qualificationService.getById(businessKey.split("\\.")[1]);
            qualification.setStatus(1);
            qualificationService.updateById(qualification);

            //相关机构添加资质
            SysOffice office = sysOfficeService.getById(qualification.getOfficeId());
            List list = Utils.stringToList(office.getRoles());
            list.add(qualification.getType());
            String s = Utils.listToString(list);
            office.setRoles(s);
            sysOfficeService.updateById(office);
        }

        return true;
    }

}
